﻿using MCPlatform.MotionLib.Base;
using MCPlatform.MotionLib.Base.AssitantClass;
using MCPlatform.MotionLib.Base.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace MCPlatform.MotionLib.Factory.Common
{
    public class ValveBase : IValve
    {
        protected NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();//打印日志
        public IIO ?IO { get; set; }
        public int BaseTimeout { get; set; } = 10000;

        public int WorkTimeout { get; set; } = 10000;

        public ushort BaseInAddress { get; set; }

        public ushort WorkInAddress { get; set; }

        public ushort BaseOutAddress { get; set; }

        public ushort WorkOutAddress { get; set; }
        public string ValveName { get; set; } = string.Empty;

        private ValveParaModel _ValveConfig = new ValveParaModel();

        public ValveParaModel ValveConfig
        {
            get { return _ValveConfig; }
            set 
            { 
                _ValveConfig = value;
                BaseTimeout = value.BasingTimeOut;
                WorkTimeout = value.WorkingTimeOut;
            }
        }

      
        public bool BaseIn
        {
            get
            { 
                if (IO == null) { return false; }
                if (BaseInAddress == 0)
                {
                    return true;
                }
                var res = IO.ReadInBit(BaseInAddress);
                return IO.ReadInBit(BaseInAddress) > 0? false:true;
            }
            set { }
        }
        public bool WorkIn
        {
            get
            {
                if (IO == null) { return false; }
                if (WorkInAddress == 0)
                {
                    return true;
                }
                var res = IO.ReadInBit(WorkInAddress);
                return IO.ReadInBit(WorkInAddress) > 0 ? false : true;
            }
            set { }
        }

        public bool BaseOut
        {
            get
            {
                if (IO == null) { return false; }

                if (BaseOutAddress == 0)
                {
                    return IO.ReadOutBit(WorkOutAddress) > 0 ? false : true;
                }

                return IO.ReadOutBit(BaseOutAddress) > 0 ? true : false;
            }
            set { }
        }
        public bool WorkOut
        {
            get
            {
                if (IO == null) { return false; }

                return IO.ReadOutBit(WorkOutAddress) > 0 ? true : false;
            }
            set { }
        }


        public async Task<bool> BasingAsync(int timeOut = 0)
        {
            if (IO == null) { return false; }
            logger.Info($"阀:{ValveName}，关闭执行： Working, 点位:Q{WorkOutAddress}");
           
            IO.WriteOutBitNolog(WorkOutAddress, 1);
            await Task.Delay(10);

            if (timeOut == 0)
            {
                timeOut = BaseTimeout;
            }

            Stopwatch sw = Stopwatch.StartNew();
            await Task.Run(async () =>
            {
                if (BaseOutAddress > 0)
                {
                    logger.Info($"阀:{ValveName}，执行： Basing, 点位:Q{BaseOutAddress}");
                    IO.WriteOutBitNolog(BaseOutAddress, 0);
                }
                
              
                while (sw.ElapsedMilliseconds < timeOut && !BaseIn)
                {
                   await Task.Delay(10);
                }
            });    

            if (sw.ElapsedMilliseconds > timeOut)
            {
                logger.Error($"阀:{ValveName}，执行：Basing, 点位:Q{BaseOutAddress}，超时！超时时间：{timeOut}");
                throw new ValveException("Basing TimeOut");
                //return false;
            }
            return  true;
        }

        public async Task<bool> WorkingAsync(int timeOut = 0)
        {
            if (IO == null) { return false; }

            if (BaseOutAddress > 0)
            {
                logger.Info($"阀:{ValveName}，关闭执行：Basing, 点位:Q{BaseOutAddress}");
                IO.WriteOutBitNolog(BaseOutAddress, 1);
                await Task.Delay(10);
            }

            if (timeOut == 0)
            {
                timeOut = WorkTimeout;
            }

            Stopwatch sw = Stopwatch.StartNew();
            await Task.Run(async () =>
            {
                logger.Info($"阀:{ValveName}，执行：Working, 点位:Q{WorkOutAddress}");
                IO.WriteOutBitNolog(WorkOutAddress, 0);

                while (sw.ElapsedMilliseconds < timeOut && !WorkIn)
                {
                    await Task.Delay(10);
                }
            });

            if (sw.ElapsedMilliseconds > timeOut)
            {
                logger.Error($"阀:{ValveName}，执行：Working, 点位:Q{WorkOutAddress}，超时！超时时间：{timeOut}");
                throw new ValveException("Basing TimeOut");
               // return false;
            }
            return true;          
        }
    }
}
